import { isObject } from '@/utils/is'

/**
 * 创建一个随机数
 * 随机字符串 + 时间戳字符串
 *
 * @param {Number} 随机长度
 * @returns {String} 当前浏览器名称
 */
export const randomString = (length = 12) => {
  const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  const dateStr = Date.now().toString(36)
  let result = ''

  for (let i = length; i > 0; --i) {
    result += str[Math.floor(Math.random() * str.length)]
  }
  if (length < dateStr.length / 2) {
    return result
  } else {
    return (
      result.substring(0, result.length - dateStr.length / 2) +
      dateStr.substring(dateStr.length / 2, dateStr.length)
    )
  }
}

/**
 * 深度合并对象，遍历合并
 * @param   {any}  src
 * @param   {any}  target
 */
export function deepMerge(src, target) {
  let key
  for (key in target) {
    src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key])
  }
  return src
}

/**
 * 根据数组中某个对象值去重
 * @param {Array} arr 数组
 * @param {String} key 对象的key标识，通过标识去重
 * @returns {Array}
 */
export function unique(arr, key) {
  const map = new Map()
  return arr.filter((item) => {
    const _item = item
    return !map.has(_item[key]) && map.set(_item[key], 1)
  })
}

/**
 * 合并数组对象中相同的key值
 * @param {Array} arr  源数组对象
 * @param {String} refer 用于合并参考相同的key
 * @param {String} key 需要执行合并的key
 * @returns {Array}
 */
export const mergeArray = (arr, refer, key) => {
  let hash = {},
    i = 0,
    res = []

  arr.forEach((item) => {
    let name = item[refer]
    if (name) {
      hash[name]
        ? item[key] && res[hash[name] - 1][key].push(item[key])
        : item[key] &&
          (hash[name] =
            ++i &&
            res.push({
              ...item,
              [key]: [item[key]],
              [refer]: name
            }))
    }
  })
  return res
}

/**
 * 拷贝文字
 */
export const copyText = (text) => {
  const inputCopy = document.createElement('input')

  inputCopy.setAttribute('readonly', 'readonly')
  inputCopy.value = text
  document.body.appendChild(inputCopy)
  inputCopy.select()
  inputCopy.setSelectionRange(0, inputCopy.value.length)
  document.execCommand('copy')
  document.body.removeChild(inputCopy)
}

/**
 * 替换文字，标注颜色
 * 根据单个字为单位
 */
export const replaceText = (text, keyword) => {
  if (keyword && keyword !== '') {
    let resStr = text
    const words = keyword.split('') || []

    words.map((str) => {
      resStr = resStr.replace(RegExp(str, 'g'), `<span style="color: #f40;">${str}</span>`)
    })
    return resStr || text
  } else {
    return text
  }
}

/**
 * 一维对象转tree对象
 *
 * @param   {Array}  dataSource     一维源数据
 * @param   {String}  parentNode    顶级节点id
 * @param   {String}  idField       子节点id字段名，默认：id
 * @param   {String}  parentField   父节点id字段名，默认：parentId
 */
export const transformTreeData = (dataSource, parentNode, idField = 'id', parentField = 'parentId') => {
  if (typeof parentNode === 'undefined') {
    throw new Error(`transformTreeData (dataSource, parentNode) -> 缺少顶级节点parentNode参数`)
  }
  if (!(dataSource instanceof Array)) {
    throw new Error(`transformTreeData (dataSource, parentNode) -> dataSource必须为数组`)
  }

  // 按照子节点id先排序，便于获取父节点对象
  let dataObjById = {}
  dataSource.map((item) => {
    dataObjById[item[idField]] = item
  })

  // 递归函数
  function getTreeData(data, parent) {
    let tree = []
    let temp
    data.map((item) => {
      if (item.parentId === parent) {
        // 存在父级节点时
        temp = getTreeData(data, item.id)
        if (temp.length > 0) {
          item.children = temp
        }
        // 在子节点中保持父节点数据
        if (dataObjById[item[parentField]]) {
          const pData = dataObjById[item[parentField]]
          item.parentNode = { ...pData }
          item.title = item.name
        } else {
          item.parentNode = {}
          item.title = item.name
        }
        tree.push(item)
      }
    })
    return tree
  }

  return getTreeData(dataSource, parentNode)
}

/**
 * tree结构转一维数组
 */
export const transformTree2Arr = (source, childrenField = 'children') => {
  let list = []
  function getList(treeData) {
    treeData.map((item) => {
      list.push({
        ...item
      })
      if (item[childrenField] && item[childrenField].length > 0) {
        getList(item[childrenField])
      }
    })
  }
  // 调用
  getList(source)

  return list
}

/**
 * 深拷贝
 */
function deepCloneFn(obj) {
  var _toString = Object.prototype.toString

  // null, undefined, non-object, function
  if (!obj || typeof obj !== 'object') {
    return obj
  }
  // DOM Node
  if (obj.nodeType && 'cloneNode' in obj) {
    return obj.cloneNode(true)
  }
  // Date
  if (_toString.call(obj) === '[object Date]') {
    return new Date(obj.getTime())
  }
  // RegExp
  if (_toString.call(obj) === '[object RegExp]') {
    var flags = []
    if (obj.global) {
      flags.push('g')
    }
    if (obj.multiline) {
      flags.push('m')
    }
    if (obj.ignoreCase) {
      flags.push('i')
    }
    return new RegExp(obj.source, flags.join(''))
  }

  var result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}
  for (var key in obj) {
    result[key] = deepCloneFn(obj[key])
  }

  return result
}

export const deepClone = (obj) => {
  return deepCloneFn(obj)
}
